function    A408()
    % 主成分分析
    % PCA通过正交变换将可能存在相关性的变量转换为线性不相关的变量，找出表达性能最优的正交基。
    % 数据集的主成分
    % 加载样本数据集。
    format long;
    clc;
    disp('主成分分析工具：');
    disp('1. 分析数据集 A408_data_1.xlsx');
    disp('2. 分析数据集 A408_data_2.xlsx');
    choice = input('请选择要运行的分析（1或2）：');
    switch choice
        case 1
            run_a1();
        case 2
            run_a2();
        otherwise
            disp('无效选择，请输入 1 或 2。');
    end
end

function run_a1()
    format long;
    % 主成分分析
    % PCA通过正交变换将可能存在相关性的变量转换为线性不相关的变量，找出表达性能最优的正交基。
    % 放大数据看看能不能放大差异
    % 数据集的主成分
    % 读取 Excel 文件中的数据
    filename = 'A408_data_1.xlsx';
    data = readtable(filename);
    
    % 提取前两列作为原料数据，最后一列作为结果
    ingredients = data{:, 1:2};                                              % 前两列是两个变量
    min_vals = min(ingredients);
    max_vals = max(ingredients);
    ingredients = (ingredients - min_vals) ./ (max_vals - min_vals);
    results = data{:, 3};                                                    % 第三列是结果
    
    % 原料数据有2个变量的24个观测值。
    % 找出原料数据的主成分。
    % 主成分系数、分数和方差
    % 计算原料数据的成分的主成分系数、分数和方差。
    [coeff8, score8, latent8] = pca(ingredients)
    % 主成分系数矩阵 coeff 的行包含两个变量的系数，其列对应于两个主成分。
    % score的每列对应一个主成分的得分每行对应一个样本的数据，表示这个样本在2个主成分方向上的坐标。
    % 向量latent存储两个主成分的方差，通常用于评估每个主成分对原始数据方差的贡献。
    % 重新构造中心化的原料数据。
    Xcentered8 = score8*coeff8'
    % Xcentered 中的新数据是将原始数据对应列减去列均值进行中心化后所得的结果，反映了样本在主成分方向上的表现。
    % 在单一图中可视化每个变量的正交主成分系数和每个观测值的主成分分数。
    figure;
    biplot(coeff8(:, 1:2), 'scores', score8(:, 1:2), 'varlabels', {'Pressure', 'Temperature'});
    xlabel('Pressure');  
    ylabel('Temperature');
    % 所有两个变量在此双标图中都用向量来表示，向量的方向和长度指示每个变量对图中两个主成分的贡献。
    
    % T方统计量在 PCA 中用于衡量样本与主成分空间中心的偏差
    % 原料数据有2个变量的24个观测值。
    % 执行主成分分析并请求T方值。
    [coeff9, score9, latent9, tsquared9] = pca(ingredients)
    % 仅请求前两个主成分，并计算请求的主成分在降维空间中的T方值。
    [coeff10, score10, latent10, tsquared10] = pca(ingredients, 'NumComponents', 2)
    % 即使指定了降维的成分空间，pca仍会使用所有两个成分计算完整空间中的T方值。
    % 降维空间中的T方值对应于降维空间中的马氏距离。
    tsqreduced10 = mahal(score10, score10)
    % 通过求完整空间中的T方值和降维空间中的马氏距离之差来计算丢弃空间中的T方值，反映了降维操作导致的信息丢失。
    tsqdiscarded10 = tsquared10 - tsqreduced10
    
    % 加权 PCA
    % 执行主成分分析时，使用变量的逆方差作为权重。
    % 使用原料数据的逆方差作为变量权重执行主成分分析。
    [wcoeff3, ~, latent3, ~, explained3] = pca(ingredients, 'VariableWeights', 'variance')
    % explained是每个主成分方差的比例，表示每个主成分解释的数据变异性的百分比。
    % 计算正交系数矩阵，对主成分系数进行标准化使得每个变量对PCA的贡献在相同的尺度上。
    coefforth = inv(diag(std(ingredients)))* wcoeff3
    % 检查新系数矩阵coefforth的正交性，在PCA中，每个主成分应该捕捉到数据中的不同方差维度。
    coefforth*coefforth'
    
    % 对缺失数据使用 ALS 进行 PCA
    % 当数据中有缺失值时，使用交替最小二乘法(ALS)算法计算主成分。
    % 原料数据有2个变量的24个观测值。
    % 使用ALS算法执行主成分分析，并显示成分系数。
    % [coeff5, score5, latent5, tsquared5, explained5] = pca(ingredients)
    % 在数据中人为引入一些缺失值（NaN）
    ingredients_with_nan = ingredients;
    % 人为插入缺失值（NaN）
    ingredients_with_nan(2, 1) = NaN;                                        % 在第二行第一列插入缺失值
    ingredients_with_nan(5, 2) = NaN;                                        % 在第五行第二列插入缺失值
    ingredients_with_nan(8, 1) = NaN;                                        % 在第八行第一列插入缺失值
    % 设置ALS算法的最大迭代次数和容忍度
    max_iter = 100;                                                          % 最大迭代次数
    tol = 1e-6;                                                              % 容忍度
    % Step 1: 初始化缺失值
    X_filled = ingredients_with_nan;                                         % 初始时，使用现有数据填充
    % Step 2: 迭代填充缺失值
    for iter = 1:max_iter
        X_prev = X_filled;                                                   % 保存上一轮的填充数据
        for i = 1:size(ingredients_with_nan, 1)                              % 对每一行进行更新
            for j = 1:size(ingredients_with_nan, 2)                          % 对每一列进行更新
                if isnan(ingredients_with_nan(i, j))                         % 如果该位置是缺失值
                    % 使用非缺失值的均值作为该位置的估算值
                    known_rows = ~isnan(X_filled(:, j));                     % 找出非缺失值的行
                    X_filled(i, j) = mean(X_filled(known_rows, j));          % 插补缺失值
                end
            end
        end
        % Step 3: 如果填充结果变化非常小，则停止迭代
        if norm(X_filled - X_prev, 'fro') < tol
            break;
        end
    end
    % Step 4: 执行PCA
    [coeff5, score5, latent5, tsquared5, explained5] = pca(X_filled)
end

function run_a2()
    format long;
    % 主成分分析
    % PCA通过正交变换将可能存在相关性的变量转换为线性不相关的变量，找出表达性能最优的正交基。
    % 数据集的主成分
    % 加载样本数据集。
    filename = 'A408_data_2.xlsx';
    data = readtable(filename);
    ingredients = data{:, 1:2};
    ingredients(:,1) = (ingredients(:,1) - min(ingredients(:,1))) / (max(ingredients(:,1)) - min(ingredients(:,1)));
    results = data{:, 3};
    
    % 原料数据有2个变量的105个观测值。
    % 找出原料数据的主成分。-
    % 主成分系数、分数和方差
    % 计算原料数据的成分的主成分系数、分数和方差。
    [coeff8, score8, latent8] = pca(ingredients)
    % 主成分系数矩阵 coeff 的行包含两个变量的系数，其列对应于两个主成分。
    % score的每列对应一个主成分的得分每行对应一个样本的数据，表示这个样本在2个主成分方向上的坐标。
    % 向量latent存储两个主成分的方差，通常用于评估每个主成分对原始数据方差的贡献。
    % 重新构造中心化的原料数据
    Xcentered8 = score8 * coeff8'
    % Xcentered 中的新数据是将原始原料数据对应列减去列均值进行中心化后所得的结果，反映了样本在主成分方向上的表现。
    % 在单一图中可视化每个变量的正交主成分系数和每个观测值的主成分分数。
    % 绘制 biplot
    figure;
    biplot(coeff8(:, 1:2), 'scores', score8(:, 1:2), 'varlabels', {'Pressure', 'Reinforcement'});
    xlabel('Reinforcement Effect');  
    ylabel('Pressure Effect');
    % 所有两个变量在此双标图中都用向量来表示，向量的方向和长度指示每个变量对图中两个主成分的贡献。
    
    % T方统计量在 PCA 中用于衡量样本与主成分空间中心的偏差
    % 原料数据有2个变量的24个观测值。
    % 执行主成分分析并请求T方值。
    [coeff9, score9, latent9, tsquared9] = pca(ingredients)
    % 仅请求前两个主成分，并计算降维空间中的 T² 值
    [coeff10, score10, latent10, tsquared10] = pca(ingredients, 'NumComponents', 2)
    % 即使指定了降维的成分空间，pca仍会使用所有两个成分计算完整空间中的T方值。
    % 降维空间中的T方值对应于降维空间中的马氏距离。
    tsqreduced10 = mahal(score10, score10)
    % 通过求完整空间中的T方值和降维空间中的马氏距离之差来计算丢弃空间中的T方值，反映了降维操作导致的信息丢失。
    tsqdiscarded10 = tsquared10 - tsqreduced10
    % 使用变量的逆方差作为权重执行 PCA

    % 加权 PCA
    % 执行主成分分析时，使用变量的逆方差作为权重。
    % 使用原料数据的逆方差作为变量权重执行主成分分析。
    [wcoeff3, ~, latent3, ~, explained3] = pca(ingredients, 'VariableWeights', 'variance')
    % explained是每个主成分方差的比例，表示每个主成分解释的数据变异性的百分比。
    % 计算正交系数矩阵，对主成分系数进行标准化使得每个变量对PCA的贡献在相同的尺度上。
    coefforth = inv(diag(std(ingredients))) * wcoeff3
     % 检查新系数矩阵coefforth的正交性，在PCA中，每个主成分应该捕捉到数据中的不同方差维度。
    coefforth*coefforth'
    
    % 对缺失数据使用 ALS 进行 PCA
    % 当数据中有缺失值时，使用交替最小二乘法(ALS)算法计算主成分。
    % 原料数据有2个变量的24个观测值。
    % 使用ALS算法执行主成分分析，并显示成分系数。
    % [coeff5, score5, latent5, tsquared5, explained5] = pca(ingredients)
    % 在数据中人为引入一些缺失值（NaN）
    ingredients_with_nan = ingredients;
    ingredients_with_nan(2, 1) = NaN;  % 在第二行第一列插入缺失值
    ingredients_with_nan(5, 2) = NaN;  % 在第五行第二列插入缺失值
    ingredients_with_nan(8, 1) = NaN;  % 在第八行第一列插入缺失值
    
    % 设置 ALS 算法参数
    max_iter = 100;  % 最大迭代次数
    tol = 1e-6;      % 容忍度
    X_filled = ingredients_with_nan;  % 初始化填充缺失值
    
    % 迭代填充缺失值
    for iter = 1:max_iter
        X_prev = X_filled;
        for i = 1:size(ingredients_with_nan, 1)
            for j = 1:size(ingredients_with_nan, 2)
                if isnan(ingredients_with_nan(i, j))
                    % 用该列非缺失值的均值填充
                    known_rows = ~isnan(X_filled(:, j));
                    X_filled(i, j) = mean(X_filled(known_rows, j));
                end
            end
        end
        if norm(X_filled - X_prev, 'fro') < tol
            break;
        end
    end
    
    % 对填充后的数据执行 PCA
    [coeff5, score5, latent5, tsquared5, explained5] = pca(X_filled)
end